#pragma once

#include "..\base\Engine.h"
#include "..\renderer\VertexDeclaration.h"
#include <vector>
#include "..\content\ResManager.h"

namespace ds {

enum VDUSAGE {
	VDU_POSITION,VDU_NORMAL,VDU_COLOR,VDU_TEXCOORD,VDU_POSITIONT
};

enum VDTYPE {
	VT_FLOAT4,VT_FLOAT3,VT_COLOR,VT_FLOAT2
};

class VertexDeclaration : public Asset {

struct VDElement {
	VDTYPE type;
	VDUSAGE usage;
};

typedef std::vector<VDElement> VDElements;

public:
	VertexDeclaration(const char* handle);
	~VertexDeclaration(void);
	void addElement(const VDTYPE& type,const VDUSAGE& usage);
	void create();
	void clear();
	IDirect3DVertexDeclaration9* get() { return m_Decl; }
	int getSize();
private:	
	IDirect3DVertexDeclaration9* m_Decl;
	VDElements m_DecElements;
	int m_Size;
};

// -----------------------------------------------
//
// -----------------------------------------------
class TransformedTexturedVertex {

public:

	float x,y,z,rwh;
	float tu,tv;

	TransformedTexturedVertex() {
		x = y = z = 0.0f;
		rwh = 1.0f;
		tu = tv = 0.0f;
	}

	TransformedTexturedVertex(float xp,float yp,float zp,float u,float v) {
		x = xp;
		y = yp;
		z = zp;
		rwh = 1.0f;
		tu = u;
		tv = v;
	}

	TransformedTexturedVertex(const Vec3& pos,const Vec2& texcoords) {
		x = pos.x;
		y = pos.y;
		z = pos.z;
		rwh = 1.0f;
		tu = texcoords.x;
		tv = texcoords.y;
	}

	static VertexDeclaration* getVertexDeclaration() {
		if ( !gEngine->getResourceManager().contains("TransformedTexturedVertex")) {
			ResourceHandle handle = gEngine->getResourceManager().createVertexDeclaration("TransformedTexturedVertex");
			VertexDeclaration* vd = gEngine->getResourceManager().getVertexDeclaration(handle);
			vd->addElement(ds::VT_FLOAT4,ds::VDU_POSITIONT);
			vd->addElement(ds::VT_FLOAT2,ds::VDU_TEXCOORD);
			vd->create();
			return vd;
		}
		else {
			return gEngine->getResourceManager().getVertexDeclaration("TransformedTexturedVertex");
		}
	}
};

// -----------------------------------------------
//
// -----------------------------------------------
class TransformedTextureColorVertex {

public:

	float x,y,z,rwh;
	float tu,tv;
	Color color;

	TransformedTextureColorVertex() {
		x = y = z = 0.0f;
		rwh = 1.0f;
		tu = tv = 0.0f;
		color = Color(1.0f,1.0f,1.0f,1.0f);
	}

	TransformedTextureColorVertex(float xp,float yp,float zp,float u,float v) {
		x = xp;
		y = yp;
		z = zp;
		rwh = 1.0f;
		tu = u;
		tv = v;
		color = Color(1.0f,1.0f,1.0f,1.0f);
	}

	TransformedTextureColorVertex(float xp,float yp,float zp,float u,float v,const Color& clr) {
		x = xp;
		y = yp;
		z = zp;
		rwh = 1.0f;
		tu = u;
		tv = v;
		color = clr;
	}

	TransformedTextureColorVertex(const Vec3& pos,const Vec2& texcoords) {
		x = pos.x;
		y = pos.y;
		z = pos.z;
		rwh = 1.0f;
		tu = texcoords.x;
		tv = texcoords.y;
		color = Color(1.0f,1.0f,1.0f,1.0f);
	}

	TransformedTextureColorVertex(const Vec3& pos,const Vec2& texcoords,const Color& clr) {
		x = pos.x;
		y = pos.y;
		z = pos.z;
		rwh = 1.0f;
		tu = texcoords.x;
		tv = texcoords.y;
		color = clr;
	}

	static VertexDeclaration* getVertexDeclaration() {
		if ( !gEngine->getResourceManager().contains("TransformedTextureColorVertex")) {
			ResourceHandle handle = gEngine->getResourceManager().createVertexDeclaration("TransformedTextureColorVertex");
			VertexDeclaration* vd = gEngine->getResourceManager().getVertexDeclaration(handle);
			vd->addElement(ds::VT_FLOAT4,ds::VDU_POSITIONT);
			vd->addElement(ds::VT_FLOAT2,ds::VDU_TEXCOORD);
			vd->addElement(ds::VT_FLOAT4,ds::VDU_COLOR);
			vd->create();
			return vd;
		}
		else {
			return gEngine->getResourceManager().getVertexDeclaration("TransformedTextureColorVertex");
		}
	}
};
// -----------------------------------------------
//
// -----------------------------------------------
class TransformedColorVertex {

public:

	float x,y,z,rwh;
	Color color;

	TransformedColorVertex() {
		x = y = z = 0.0f;
		rwh = 1.0f;
		color = Color(1.0f,1.0f,1.0f,1.0f);
	}

	TransformedColorVertex(float xp,float yp,float zp,const Color& color) {
		x = xp;
		y = yp;
		z = zp;
		rwh = 1.0f;
		this->color = color;
	}

	TransformedColorVertex(const Vec3& pos,const Color& color) {
		x = pos.x;
		y = pos.y;
		z = pos.z;
		rwh = 1.0f;
		this->color = color;
	}

	static VertexDeclaration* getVertexDeclaration() {
		if ( !gEngine->getResourceManager().contains("TransformedColorVertex")) {
			ResourceHandle handle = gEngine->getResourceManager().createVertexDeclaration("TransformedColorVertex");
			VertexDeclaration* vd = gEngine->getResourceManager().getVertexDeclaration(handle);
			vd->addElement(ds::VT_FLOAT4,ds::VDU_POSITIONT);
			vd->addElement(ds::VT_FLOAT4,ds::VDU_COLOR);
			vd->create();
			return vd;
		}
		else {
			return gEngine->getResourceManager().getVertexDeclaration("TransformedColorVertex");
		}
	}
};

class PositionTextureVertex {

public:

	float x,y,z;
	float tu,tv;

	PositionTextureVertex() {
		x = y = z = 0.0f;
		tu = tv = 0.0f;
	}

	PositionTextureVertex(const Vec3& pos,const Vec2& texcoords) {
		x = pos.x;
		y = pos.y;
		z = pos.z;
		tu = texcoords.x;
		tv = texcoords.y;
	}

	static VertexDeclaration* getVertexDeclaration() {
		if ( !gEngine->getResourceManager().contains("PositionTextureVertex")) {
			ResourceHandle handle = gEngine->getResourceManager().createVertexDeclaration("PositionTextureVertex");
			VertexDeclaration* vd = gEngine->getResourceManager().getVertexDeclaration(handle);
			vd->addElement(ds::VT_FLOAT3,ds::VDU_POSITION);
			vd->addElement(ds::VT_FLOAT2,ds::VDU_TEXCOORD);
			vd->create();
			return vd;
		}
		else {
			return gEngine->getResourceManager().getVertexDeclaration("PositionTextureVertex");
		}
	}
};

class PositionTextureNormalsVertex {

public:

	float x,y,z;
	float tu,tv;
	float nx,ny,nz;

	PositionTextureNormalsVertex() {
		x = y = z = 0.0f;
		tu = tv = 0.0f;
		nx = ny = nz = 0.0f;
	}

	PositionTextureNormalsVertex(const Vec3& pos,const Vec2& texcoords,const Vec3& normals) {
		x = pos.x;
		y = pos.y;
		z = pos.z;
		tu = texcoords.x;
		tv = texcoords.y;
		nx = normals.x;
		ny = normals.y;
		nz = normals.z;
	}

	static VertexDeclaration* getVertexDeclaration() {
		if ( !gEngine->getResourceManager().contains("PositionTextureNormalsVertex")) {
			ResourceHandle handle = gEngine->getResourceManager().createVertexDeclaration("PositionTextureNormalsVertex");
			VertexDeclaration* vd = gEngine->getResourceManager().getVertexDeclaration(handle);
			vd->addElement(ds::VT_FLOAT3,ds::VDU_POSITION);
			vd->addElement(ds::VT_FLOAT2,ds::VDU_TEXCOORD);
			vd->addElement(ds::VT_FLOAT3,ds::VDU_NORMAL);
			vd->create();
			return vd;
		}
		else {
			return gEngine->getResourceManager().getVertexDeclaration("PositionTextureNormalsVertex");
		}
	}
};

};
